import json
import os
from pathlib import Path
import hashlib, time, requests
import uuid
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from functional import seq

def ensure_gbk_encoding(text):
    '''
    保证文本是可被GBK编码的
    例如，对于文本gbk编码报错，调用此函数可以去除报错字符
    ```txt
    𝑛
    ```
    '''
    new_text = ""
    for each in text:
        try:
            each.encode('gbk')
            new_text += each
        except Exception as e:
            pass
    return new_text

### YOUDAO 匿名API
class YouDaoAnony:
    s = requests.session()
    secretKey = 'fsdsogkndfokasodnaso'
    
    @staticmethod
    def get_salt(key, t):
        paramStr = f'client=fanyideskweb&mysticTime={t}&product=webfanyi&key={key}'
        sign = hashlib.md5(paramStr.encode()).hexdigest() 
        return sign
    
    @classmethod    
    def translate(cls, text):
        text = ensure_gbk_encoding(text)
        t = int(time.time() * 1000)
        data = {
            'i': text,
            'from': 'auto',
            'to': '',
            'dictResult': True,
            'keyid': 'webfanyi',
            'sign': cls.get_salt(cls.secretKey, t),
            'client': "fanyideskweb",
            'product': "webfanyi",
            'appVersion': "1.0.0",
            'vendor': "web",
            'pointParam': "client,mysticTime,product",
            'mysticTime': t,
            'keyfrom': "fanyi.web"
        }

        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
            'Host':'dict.youdao.com',
            'Origin':'https://fanyi.youdao.com',
            'Referer':'https://fanyi.youdao.com/',
        }

        # 请求登录页面以获取Cookie
        resp = cls.s.get('https://dict.youdao.com/login/acc/query/accountinfo')

        if resp.status_code != 200:
            print('与服务器连接失败！！！')
            exit()

        headers['Cookie'] = '; '.join([f'{k}={v}' for k,v in resp.cookies.get_dict().items()])

        resp = cls.s.post('https://dict.youdao.com/webtranslate', verify=False, headers=headers, data=data)

        encrypted_data = resp.content.decode().replace('-','+').replace('_','/')
        data = json.loads(cls.decryption(encrypted_data))
        
        return (seq(data['translateResult'][0])
                .map(lambda x: x["tgt"])
                .make_string(' '))
        
    @staticmethod
    def decryption(encrypted_data):
        decode_key = bytes([8, 20, 157, 167, 60, 89, 206, 98, 85, 91, 1, 233, 47, 52, 232, 56])
        decode_iv = bytes([210, 187, 27, 253, 232, 59, 56, 195, 68, 54, 99, 87, 183, 156, 174, 28])
        cipher = AES.new(decode_key, AES.MODE_CBC, decode_iv)
        return unpad(cipher.decrypt(base64.b64decode(encrypted_data)), 16).decode()

### YOUDAO 官方API
# 使用API key 时,请求频率限制为每小时1000次，超过限制会被封禁。
def yd_translate(cont):
    cont = ensure_gbk_encoding(cont)
    data = {
        'from': 'auto', 'to': 'auto', 'signType': 'v3', 'curtime': str(int(time.time())), 'salt': str(uuid.uuid1()),
        'appKey': '11a9400bc2913af2', 
        'q': cont
    }
    truncate = lambda q: q if len(q) <= 20 else q[0:10] + str(len(q)) + q[len(q) - 10:len(q)]
    signStr = data['appKey'] + truncate(cont) + data['salt'] + data['curtime'] + 'p9cmIkzrBYibWTxBSzJqvVV9ris2HrUZ'
    hash_algorithm = hashlib.sha256()
    hash_algorithm.update(signStr.encode('utf-8'))
    data['sign'] = hash_algorithm.hexdigest()

    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    resp_text = requests.post('https://openapi.youdao.com/api', data=data, headers=headers).content.decode('utf-8')
    return json.loads(resp_text)['translation'][0]
    

if __name__ == '__main__':
    os.chdir(Path(__file__).parent)
    text = "高数考完了，又到了数学老师难办的时候。数学老师想捞同学一把，她总是要一遍遍地给某些同学增加分数（均为正整数），又要注意最低分是多少。由于工作量很大，你能帮帮她吗？"
    print(yd_translate(text))
